package com.ruoyi.door.controller.admin.house;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.Hutool;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.easy.query.core.basic.api.select.Query;
import com.easy.query.core.proxy.core.Expression;
import com.easy.query.core.proxy.sql.Select;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.entity.proxy.SysDeptProxy;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.SysDeptUtil;
import com.ruoyi.common.utils.excel.ExcelUtils;
import com.ruoyi.door.controller.admin.adsl.vo.DoorAdslImportVO;
import com.ruoyi.door.controller.admin.house.vo.DoorHouseExportVO;
import com.ruoyi.door.controller.admin.house.vo.DoorHouseImportVO;
import com.ruoyi.door.controller.admin.house.vo.DoorHouseImportFailureVO;
import com.ruoyi.door.utils.HouseUtil;
import lombok.extern.slf4j.Slf4j;
import com.ruoyi.door.controller.admin.house.vo.DoorHouseReqVO;
import com.ruoyi.door.controller.admin.house.vo.DoorHouseRespVO;
import com.ruoyi.door.controller.admin.house.vo.proxy.DoorHouseRespVOProxy;
import com.ruoyi.door.domain.DoorAdsl;
import com.ruoyi.door.domain.DoorLandlord;
import com.ruoyi.door.service.DoorHouseService;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbookType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.enums.BusinessType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.constant.HttpStatus;
import com.easy.query.core.api.pagination.EasyPageResult;
import com.easy.query.api.proxy.client.EasyEntityQuery;
import com.easy.query.api.proxy.entity.select.EntityQueryable;
import com.ruoyi.door.domain.proxy.DoorHouseProxy;
import com.ruoyi.door.domain.DoorHouse;
import com.ruoyi.common.utils.poi.ExcelUtil;
import org.springframework.web.multipart.MultipartFile;

import static cn.hutool.core.io.FileMagicNumber.XLS;
import static org.apache.poi.xssf.usermodel.XSSFWorkbookType.XLSX;
import static org.openxmlformats.schemas.spreadsheetml.x2006.main.STPaneState.SPLIT;

/**
 * 房产Controller
 *
 * @author ruoyi
 * @date 2025-06-21
 */
@Api(value = "房产管理", tags = "房产管理")
@RestController
@RequestMapping("/door/house")
@Slf4j
public class DoorHouseController extends BaseController {
    @Autowired
    private EasyEntityQuery easyEntityQuery;
    @Autowired
    private ISysDeptService isysDeptService;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private DoorHouseService doorHouseService;
    @Autowired
    private RedisCache redisCache;

    private EntityQueryable<DoorHouseRespVOProxy, DoorHouseRespVO> buildQuery(DoorHouseReqVO doorHouse) {
        EntityQueryable<DoorHouseRespVOProxy, DoorHouseRespVO> queryable = easyEntityQuery.queryable(DoorHouse.class)
                .leftJoin(SysUser.class, (s1, s2) -> s1.landlordId().eq(s2.userId()))
                .leftJoin(SysDept.class, (h, u, d1) -> h.country().eq(d1.deptId()))
                .leftJoin(SysDept.class, (h, u, d1, d2) -> h.province().eq(d2.deptId()))
                .leftJoin(SysDept.class, (h, u, d1, d2, d3) -> h.city().eq(d3.deptId()))
                .leftJoin(SysDept.class, (h, u, d1, d2, d3, d4) -> h.district().eq(d4.deptId()))
                .leftJoin(SysDept.class, (h, u, d1, d2, d3, d4, d5) -> h.street().eq(d5.deptId()))
                .leftJoin(SysDept.class, (h, u, d1, d2, d3, d4, d5, d6) -> h.village().eq(d6.deptId()))
                .where((h, u, d1, d2, d3, d4, d5, d6) -> {
                    if (doorHouse.getId() != null) {
                        h.id().eq(doorHouse.getId());
                    }
                    if (doorHouse.getUserId() != null) {
                        u.userId().eq(doorHouse.getUserId());
                    }
                    if (doorHouse.getLandlordId() != null) {
                        h.landlordId().eq(doorHouse.getLandlordId());
                    }
                    if (doorHouse.getCountry() != null) {
                        h.country().eq(doorHouse.getCountry());
                    }
                    if (doorHouse.getProvince() != null) {
                        h.province().eq(doorHouse.getProvince());
                    }
                    if (doorHouse.getCity() != null) {
                        h.city().eq(doorHouse.getCity());
                    }
                    if (doorHouse.getDistrict() != null) {
                        h.district().eq(doorHouse.getDistrict());
                    }
                    if (doorHouse.getStreet() != null) {
                        h.street().eq(doorHouse.getStreet());
                    }
                    if (doorHouse.getVillage() != null) {
                        h.village().eq(doorHouse.getVillage());
                    }
                    if (StrUtil.isNotEmpty(doorHouse.getDoor())) {
                        h.door().like(doorHouse.getDoor());
                    }
                    if (StrUtil.isNotEmpty(doorHouse.getAddress())) {
                        h.address().like(doorHouse.getAddress());
                    }
                    if (StrUtil.isNotEmpty(doorHouse.getLandlordName())) {
                        u.nickName().like(doorHouse.getLandlordName());
                    }
                    if (StrUtil.isNotEmpty(doorHouse.getLandlordPhone())) {
                        u.phonenumber().like(doorHouse.getLandlordPhone());
                    }
                    if (doorHouse.getDeptId() != null) {
                        Query<Long> longQuery = easyEntityQuery.queryable(SysDept.class)
                                .where(s -> {
                                    s.or(() -> {
                                        s.deptId().eq(doorHouse.getDeptId());
                                        s.expression().sql("find_in_set({0},{1})", c -> {
                                            c.value(doorHouse.getDeptId()).expression(s.ancestors());
                                        });
                                    });
                                }).selectColumn(SysDeptProxy::deptId);
                        h.deptId().in(longQuery);
                    }
                })
                .select((h, u, d1, d2, d3, d4, d5, d6) -> {
                            DoorHouseRespVOProxy r = new DoorHouseRespVOProxy();
                            r.selectAll(h);
                            r.countryName().set(d1.deptName());
                            r.provinceName().set(d2.deptName());
                            r.cityName().set(d3.deptName());
                            r.districtName().set(d4.deptName());
                            r.streetName().set(d5.deptName());
                            r.villageName().set(d6.deptName());
                            r.landlordName().set(u.nickName());
                            r.landlordPhone().set(u.phonenumber());
                            return r;
                        }
                );
        return queryable;
    }

    /**
     * 查询房产列表
     */
    @ApiOperation("查询房产列表")
    @GetMapping("/list")
    @Anonymous
    public TableDataInfo list(DoorHouseReqVO doorHouse) {
        EasyPageResult<DoorHouseRespVO> pageResult = buildQuery(doorHouse)
                .toPageResult(TableSupport.buildPageRequest().getPageNum(),
                        TableSupport.buildPageRequest().getPageSize());
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(pageResult.getData());
        rspData.setTotal(pageResult.getTotal());
        return rspData;
    }

    /**
     * 导出房产列表
     */
    @ApiOperation("导出房产列表")
    @Log(title = "房产", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, DoorHouseReqVO doorHouse) {
        List<DoorHouseRespVO> list = buildQuery(doorHouse).toList();
        List<DoorHouseExportVO> houseImportVOS = BeanUtil.copyToList(list, DoorHouseExportVO.class);
        houseImportVOS.forEach(x -> {
            //x.setBalance(x.getBalance1());
        });
        ExcelUtil<DoorHouseExportVO> util = new ExcelUtil<DoorHouseExportVO>(DoorHouseExportVO.class);
        util.exportExcel(response, houseImportVOS, "房产数据");
    }

    /**
     * 获取房产详细信息
     */
    @ApiOperation("获取房产详细信息")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(easyEntityQuery.queryable(DoorHouse.class).where(x -> x.id().eq(id))
                .firstOrNull());
    }

    /**
     * 新增房产
     */
    @ApiOperation("新增房产")
    @Log(title = "房产", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody DoorHouse doorHouse) {
        //根据新的余额重新计算到期时间
        doorHouse.setEndDate(HouseUtil.calculateEndDateFromBaseDate(doorHouse.getBalance(), doorHouse.getMonthPrice()));
        doorHouse.setStartDate(new DateTime(LocalDate.of(cn.hutool.core.date.DateUtil.thisYear(), DateUtil.thisMonth()+1, 1)));

        long rows = easyEntityQuery.insertable(doorHouse).executeRows();
        return toAjax(rows > 0);
    }

    /**
     * 修改房产
     */
    @ApiOperation("修改房产")
    @Log(title = "房产", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody DoorHouse doorHouse) {
        //计算结束日期
        //根据新的余额重新计算到期时间
        doorHouse.setEndDate(HouseUtil.calculateEndDateFromBaseDate(doorHouse.getBalance(), doorHouse.getMonthPrice()));
        doorHouse.setStartDate(new DateTime(LocalDate.of(DateUtil.thisYear(), DateUtil.thisMonth()+1, 1)));

        return toAjax(easyEntityQuery.updatable(doorHouse).executeRows() > 0);
    }

    /**
     * 删除房产
     */
    @ApiOperation("删除房产")
    @Log(title = "房产", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        long rows = easyEntityQuery.deletable(DoorHouse.class)
                .disableLogicDelete()
                .allowDeleteStatement(true)
                .where(x -> x.id().in(ids))
                .executeRows();
        return toAjax(rows > 0);
    }

    @GetMapping("/importTemplate")
    @ApiOperation("房产导入模板")
    @Anonymous
    public void importTemplate(HttpServletResponse response) throws IOException {
        String fileName = "房产模板" + DateUtils.getTime() + ".xlsx";
        String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
        InputStream stream = ResourceUtil.getStream("classpath:" + "template/房产模板.xlsx");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);
        ServletOutputStream out = response.getOutputStream();
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = stream.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
        out.flush();
        out.close();
    }


    @PostMapping("/importData")
    @ApiOperation("房产导入")
    @Log(title = "房产管理", businessType = BusinessType.IMPORT)
    public void importData(MultipartFile file, boolean updateSupport, HttpServletResponse response) throws Exception {
        String uuid = IdUtil.fastUUID();
        Map<String, Object> result = doorHouseService.importData(file, uuid);
        
        @SuppressWarnings("unchecked")
        List<DoorHouseImportFailureVO> failureList = (List<DoorHouseImportFailureVO>) result.get("failureList");
        
        // 设置Excel响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        
        if (failureList != null && !failureList.isEmpty()) {
            // 有失败数据，返回包含失败信息的Excel文件
            String fileName = "房产导入失败数据_" + DateUtils.getTime() + ".xlsx";
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);
            
            ExcelUtil<DoorHouseImportFailureVO> util = new ExcelUtil<DoorHouseImportFailureVO>(DoorHouseImportFailureVO.class);
            util.exportExcel(response, failureList, "失败数据");
        } else {
            // 没有失败数据，返回空的Excel文件
            String fileName = "房产导入成功_" + DateUtils.getTime() + ".xlsx";
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);
            
            // 创建空的失败数据列表
            List<DoorHouseImportFailureVO> emptyList = new ArrayList<>();
            ExcelUtil<DoorHouseImportFailureVO> util = new ExcelUtil<DoorHouseImportFailureVO>(DoorHouseImportFailureVO.class);
            util.exportExcel(response, emptyList, "导入结果");
        }
    }
    @GetMapping("/importDataStatus")
    @ApiOperation("房产导入状态")
    @Log(title = "房产管理", businessType = BusinessType.IMPORT)
    public AjaxResult getImportDataStatus(String uuid) throws Exception {
        return AjaxResult.success(redisCache.getCacheObject("houseimport"+uuid));
    }

    /**
     * 更新房产到期时间
     * 根据房产的 startDate 和当前月份计算月份差，扣减相应的费用，并更新到期时间
     */
    @PutMapping("/updateEndDate/{houseId}")
    @ApiOperation("更新房产到期时间")
    @Log(title = "房产管理", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('door:house:edit')")
    public AjaxResult updateEndDate(@PathVariable Long houseId) {
        // 查询房产信息
        DoorHouse house = easyEntityQuery.queryable(DoorHouse.class)
                .where(h -> h.id().eq(houseId))
                .firstOrNull();
        
        if (house == null) {
            return AjaxResult.error("房产不存在");
        }
        
        // 调用服务方法更新到期时间
        boolean success = doorHouseService.updateHouseEndDate(house);
        
        return success ? AjaxResult.success("更新成功") : AjaxResult.error("更新失败");
    }

}